#include "udp-net-communication.h"



UdpNetCommunication::UdpNetCommunication(const string &localIP, uint32_t localPort)
{
	//创建套接字
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0)
	{
		perror("Fail to create socket for udp");
		return;
	}

	//绑定IP地址
	struct sockaddr_in sockaddr;
	sockaddr.sin_family      = AF_INET;
	sockaddr.sin_addr.s_addr = inet_addr(localIP.c_str());
	sockaddr.sin_port        = htons(localPort);
	int ret                  = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
	if(ret < 0)
	{
		perror("Fail to bind");
		return;
	}
}

/**
 * 发送paket
*/
bool UdpNetCommunication::sendPacket(const vector<uint8_t> &packet)
{

	struct sockaddr_in peerAddr;
	peerAddr.sin_family      = AF_INET;
	peerAddr.sin_addr.s_addr = inet_addr(peerIP.c_str());
	peerAddr.sin_port        = htons(peerPort);
	int ret                  = sendto(fd,
                     packet.data(), packet.size(), 0,
                     (struct sockaddr *)&peerAddr, sizeof(peerAddr));
	if(ret < 0)
	{
		perror("UDP Fail to sendto");
		return false;
	}

	return true;
}

/**
 * 接收Packet 消息存到packet中
*/
bool UdpNetCommunication::recvPacket(vector<uint8_t> &packet, int timeout)
{
	fd_set readfds;

	struct timeval  waittime = {.tv_sec = timeout};
	struct timeval *ptimeout = timeout < 0 ? nullptr : &waittime;

	FD_ZERO(&readfds);
	FD_SET(fd, &readfds);

	int ret = select(fd + 1, &readfds, NULL, NULL, ptimeout);
	if(ret < 0)
	{
		perror("Fail to select \n");
		return false;
	}
	else if(ret == 0)
	{
		fprintf(stderr, "Select timeout\n");
		return false;
	}

	uint8_t            buf[1500];
	struct sockaddr_in peerAddr;
	socklen_t          addrlen = sizeof(struct sockaddr);
	int                size    = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&peerAddr, &addrlen);
	if(size < 0)
	{
		perror("Fail to recvfrom \n");
		return false;
	}
	packet = vector<uint8_t>(buf, buf + size);
	//获取对方的ip和端口
	peerIP   = inet_ntoa(peerAddr.sin_addr);
	peerPort = ntohs(peerAddr.sin_port);

	return true;
}
